package com.sikaryofficial.backend.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sikaryofficial.backend.domain.dto.req.AddressUserListReq;
import com.sikaryofficial.backend.domain.dto.req.AddressUserReq;
import com.sikaryofficial.backend.domain.dto.resp.AddressUserListDTO;
import com.sikaryofficial.backend.domain.entity.Address;
import com.sikaryofficial.backend.domain.entity.UserAddress;
import com.sikaryofficial.backend.domain.mapping.AddressMapping;
import com.sikaryofficial.backend.domain.mapping.UserAddressMapping;
import com.sikaryofficial.backend.service.IAddressService;
import com.sikaryofficial.backend.service.IUserAddressService;
import com.sikaryofficial.common.core.exception.ServiceException;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.system.api.model.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : qinjinyuan
 * @desc : 收货地址管理服务
 * @date : 2023/10/30 15:39
 */
@Service
@Slf4j
@SuppressWarnings(value="unchecked")
public class UserAddressManager {

    @Autowired
    private IUserAddressService addressUserService;

    @Autowired
    private IAddressService addressService;

    /**
     * 分页查询收货地址列表
     *
     * @param req
     * @return
     */
    public IPage<AddressUserListDTO> listPage(AddressUserListReq req) {
        // 按照创建时间排序
        Page<UserAddress> customerPage = new Page<>(req.getPageNum(), req.getPageSize());
        IPage<UserAddress> userAddressPage = addressUserService.page(customerPage,new LambdaQueryWrapper<UserAddress>()
                .eq(UserAddress::getDeletedVersion, 0L)
                .eq(UserAddress::getCreatedBy, SecurityUtils.getUserId())
                .eq(UserAddress::getHasPayment, req.getHasPayment())
               .orderByAsc(UserAddress::getCreatedTime)
        );
        if (Objects.isNull(userAddressPage) || userAddressPage.getRecords().isEmpty()) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        IPage<AddressUserListDTO> evaluateDTOIPage = userAddressPage.convert(UserAddressMapping.INSTANCE::coverToResp);
        List<AddressUserListDTO> addressUserListDTOList = evaluateDTOIPage.getRecords();
        List<Long> addressIds = addressUserListDTOList.stream().map(AddressUserListDTO::getAddressId).collect(Collectors.toList());
        List<Address> addressList = Lists.newArrayList();
        if (CollUtil.isNotEmpty(addressIds)) {
            addressList = addressService.list(new LambdaQueryWrapper<Address>()
                    .eq(Address::getDeletedVersion, 0L)
                    .in(Address::getAddressId, addressIds)
            );
        }
        if (CollUtil.isEmpty(addressList)) {
            return evaluateDTOIPage;
        }
        List<AddressDTO> addressDTOList = AddressMapping.INSTANCE.coverListToResp(addressList);
        // 构建map集合
        Map<Long, AddressDTO> addressDTOMap =
                addressDTOList.stream().collect(Collectors.toMap(AddressDTO::getAddressId, Function.identity(), (k1, k2) -> k1));
        // 填充DTO中地址相关字段
        addressUserListDTOList.forEach(item -> {
            AddressDTO addressDTO = addressDTOMap.get(item.getAddressId());
            Optional.ofNullable(addressDTO).ifPresent(item::setAddress);
        });
        return evaluateDTOIPage;
    }

    /**
     * 保存收货地址
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAddress(AddressUserReq req) {
        checkParam(req);
        UserAddress addressUser = UserAddressMapping.INSTANCE.coverToReq(req);
        // 默认地址排他处理
        if (Objects.nonNull(req.getAddressDefault()) && Objects.equals(req.getAddressDefault(), 0)) {
            addressUserService.update(new LambdaUpdateWrapper<UserAddress>()
                    .set(UserAddress::getAddressDefault, 1)
                    .set(UserAddress::getUpdatedTime, new Date())
                    .set(UserAddress::getUpdatedBy, SecurityUtils.getUserId())
                    .eq(UserAddress::getAddressDefault, 0)
                    .eq(UserAddress::getDeletedVersion, 0L)
                    .eq(UserAddress::getCreatedBy, SecurityUtils.getUserId())
            );
        }
        if (Objects.isNull(req.getUserAddressId())) {
            // 判定是否为第1个地址
            int count = addressUserService.count(new LambdaQueryWrapper<UserAddress>()
                    .eq(UserAddress::getDeletedVersion, 0L)
                   .eq(UserAddress::getCreatedBy, SecurityUtils.getUserId())
            );
            addressUser.setAddressDefault(count == 0 ? count : addressUser.getAddressDefault());
            addressUser.setUserAddressId(IdWorker.getId());
            addressUser.setCreatedBy(SecurityUtils.getUserId());
            addressUser.setCreatedTime(new Date());
            return addressUserService.save(addressUser);
        } else {
            addressUser.setUpdatedBy(SecurityUtils.getUserId());
            addressUser.setUpdatedTime(new Date());
            return addressUserService.update(addressUser,new LambdaUpdateWrapper<UserAddress>()
                    .eq(UserAddress::getUserAddressId, addressUser.getUserAddressId())
                    .eq(UserAddress::getDeletedVersion, 0L)
            );
        }
    }

    private void checkParam(AddressUserReq req) {
        if (req.getHasPayment() == 1) {
            validateFields(req.getPaymentAccount(), req.getFirstName(), req.getLastName(), req.getEmail());
        }
        if (req.getHasPayment() == 0) {
            validateFields(req.getAddressDetail(), req.getFirstName(), req.getLastName(), req.getPhoneNumber(), req.getEmail());
        }
    }

    private void validateFields(String... fields) {
        for (String field : fields) {
            if (CharSequenceUtil.isBlank(field)) {
                throw new ServiceException("Please fill in all required fields");
            }
        }
    }

    /**
     * 删除收货地址
     *
     * @param userAddressId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUserAddress(Long userAddressId, Long userId) {
        // 逻辑删除数据
        return addressUserService.update(new LambdaUpdateWrapper<UserAddress>()
                .set(UserAddress::getDeletedVersion, userAddressId)
                .set(UserAddress::getUpdatedTime, new Date())
                .set(UserAddress::getUpdatedBy, userId)
                .eq(UserAddress::getUserAddressId, userAddressId)
                .eq(UserAddress::getDeletedVersion, 0L)
                .eq(UserAddress::getCreatedBy, userId)
        );
    }
}
